#include <utility>
#include <stdlib.h>
#include <time.h>
#include "GameModel.h"

GomokuGameEngine::GomokuGameEngine()
{

}

void GomokuGameEngine::initializeGame(GomokuGameMode mode)
{
    currentMode = mode;
    // 初始棋盘
    boardState.clear();
    for (int i = 0; i < BOARD_DIMENSION; i++)
    {
        std::vector<int> lineBoard;
        for (int j = 0; j < BOARD_DIMENSION; j++)
            lineBoard.push_back(0);
        boardState.push_back(lineBoard);
    }

    // 如果是AI模式，需要初始化评分数组
    if (currentMode == HUMAN_VS_AI)
    {
        positionScores.clear();
        for (int i = 0; i < BOARD_DIMENSION; i++)
        {
            std::vector<int> lineScores;
            for (int j = 0; j < BOARD_DIMENSION; j++)
                lineScores.push_back(0);
            positionScores.push_back(lineScores);
        }
    }

    // 己方下为true,对方下位false
    isPlayerTurn = true;
}

void GomokuGameEngine::updateBoard(int row, int col)
{
    if (isPlayerTurn)
        boardState[row][col] = 1;
    else
        boardState[row][col] = -1;

    // 换手
    isPlayerTurn = !isPlayerTurn;
}

void GomokuGameEngine::humanMove(int row, int col)
{
    updateBoard(row, col);
}

void GomokuGameEngine::aiMove(int &selectedRow, int &selectedCol)
{
    // 计算评分
    evaluatePositions();

    // 从评分中找出最大分数的位置
    int maxScore = 0;
    std::vector<std::pair<int, int>> maxPoints;

    for (int row = 1; row < BOARD_DIMENSION; row++)
        for (int col = 1; col < BOARD_DIMENSION; col++)
        {
            // 前提是这个坐标是空的
            if (boardState[row][col] == 0)
            {
                if (positionScores[row][col] > maxScore)
                {
                    maxPoints.clear();
                    maxScore = positionScores[row][col];
                    maxPoints.push_back(std::make_pair(row, col));
                }
                else if (positionScores[row][col] == maxScore)
                    maxPoints.push_back(std::make_pair(row, col));
            }
        }

    // 随机落子，如果有多个点的话
    srand((unsigned)time(0));
    int index = rand() % maxPoints.size();

    std::pair<int, int> pointPair = maxPoints.at(index);
    selectedRow = pointPair.first;
    selectedCol = pointPair.second;
    updateBoard(selectedRow, selectedCol);
}

void GomokuGameEngine::evaluatePositions()
{
    int playerStones = 0;
    int aiStones = 0;
    int emptySpaces = 0;

    // 清空评分数组
    positionScores.clear();
    for (int i = 0; i < BOARD_DIMENSION; i++)
    {
        std::vector<int> lineScores;
        for (int j = 0; j < BOARD_DIMENSION; j++)
            lineScores.push_back(0);
        positionScores.push_back(lineScores);
    }

    for (int row = 0; row < BOARD_DIMENSION; row++)
        for (int col = 0; col < BOARD_DIMENSION; col++)
        {
            if (row > 0 && col > 0 && boardState[row][col] == 0)
            {
                for (int y = -1; y <= 1; y++)
                    for (int x = -1; x <= 1; x++)
                    {
                        playerStones = 0;
                        aiStones = 0;
                        emptySpaces = 0;

                        if (!(y == 0 && x == 0))
                        {
                            // 对玩家白子评分
                            for (int i = 1; i <= 4; i++)
                            {
                                if (row + i * y > 0 && row + i * y < BOARD_DIMENSION &&
                                    col + i * x > 0 && col + i * x < BOARD_DIMENSION &&
                                    boardState[row + i * y][col + i * x] == 1)
                                {
                                    playerStones++;
                                }
                                else if (row + i * y > 0 && row + i * y < BOARD_DIMENSION &&
                                         col + i * x > 0 && col + i * x < BOARD_DIMENSION &&
                                         boardState[row + i * y][col + i * x] == 0)
                                {
                                    emptySpaces++;
                                    break;
                                }
                                else
                                    break;
                            }

                            for (int i = 1; i <= 4; i++)
                            {
                                if (row - i * y > 0 && row - i * y < BOARD_DIMENSION &&
                                    col - i * x > 0 && col - i * x < BOARD_DIMENSION &&
                                    boardState[row - i * y][col - i * x] == 1)
                                {
                                    playerStones++;
                                }
                                else if (row - i * y > 0 && row - i * y < BOARD_DIMENSION &&
                                         col - i * x > 0 && col - i * x < BOARD_DIMENSION &&
                                         boardState[row - i * y][col - i * x] == 0)
                                {
                                    emptySpaces++;
                                    break;
                                }
                                else
                                    break;
                            }

                            if (playerStones == 1)
                                positionScores[row][col] += 10;
                            else if (playerStones == 2)
                            {
                                if (emptySpaces == 1)
                                    positionScores[row][col] += 30;
                                else if (emptySpaces == 2)
                                    positionScores[row][col] += 40;
                            }
                            else if (playerStones == 3)
                            {
                                if (emptySpaces == 1)
                                    positionScores[row][col] += 60;
                                else if (emptySpaces == 2)
                                    positionScores[row][col] += 110;
                            }
                            else if (playerStones == 4)
                                positionScores[row][col] += 10100;

                            emptySpaces = 0;

                            // 对AI黑子评分
                            for (int i = 1; i <= 4; i++)
                            {
                                if (row + i * y > 0 && row + i * y < BOARD_DIMENSION &&
                                    col + i * x > 0 && col + i * x < BOARD_DIMENSION &&
                                    boardState[row + i * y][col + i * x] == -1)
                                {
                                    aiStones++;
                                }
                                else if (row + i * y > 0 && row + i * y < BOARD_DIMENSION &&
                                         col + i * x > 0 && col + i * x < BOARD_DIMENSION &&
                                         boardState[row + i * y][col + i * x] == 0)
                                {
                                    emptySpaces++;
                                    break;
                                }
                                else
                                    break;
                            }

                            for (int i = 1; i <= 4; i++)
                            {
                                if (row - i * y > 0 && row - i * y < BOARD_DIMENSION &&
                                    col - i * x > 0 && col - i * x < BOARD_DIMENSION &&
                                    boardState[row - i * y][col - i * x] == -1)
                                {
                                    aiStones++;
                                }
                                else if (row - i * y > 0 && row - i * y < BOARD_DIMENSION &&
                                         col - i * x > 0 && col - i * x < BOARD_DIMENSION &&
                                         boardState[row - i * y][col - i * x] == 0)
                                {
                                    emptySpaces++;
                                    break;
                                }
                                else
                                    break;
                            }

                            if (aiStones == 0)
                                positionScores[row][col] += 5;
                            else if (aiStones == 1)
                                positionScores[row][col] += 10;
                            else if (aiStones == 2)
                            {
                                if (emptySpaces == 1)
                                    positionScores[row][col] += 25;
                                else if (emptySpaces == 2)
                                    positionScores[row][col] += 50;
                            }
                            else if (aiStones == 3)
                            {
                                if (emptySpaces == 1)
                                    positionScores[row][col] += 55;
                                else if (emptySpaces == 2)
                                    positionScores[row][col] += 100;
                            }
                            else if (aiStones >= 4)
                                positionScores[row][col] += 10000;
                        }
                    }
            }
        }
}

bool GomokuGameEngine::checkVictory(int row, int col)
{
    // 水平方向
    for (int i = 0; i < 5; i++)
    {
        if (col - i > 0 &&
            col - i + 4 < BOARD_DIMENSION &&
            boardState[row][col - i] == boardState[row][col - i + 1] &&
            boardState[row][col - i] == boardState[row][col - i + 2] &&
            boardState[row][col - i] == boardState[row][col - i + 3] &&
            boardState[row][col - i] == boardState[row][col - i + 4])
            return true;
    }

    // 竖直方向
    for (int i = 0; i < 5; i++)
    {
        if (row - i > 0 &&
            row - i + 4 < BOARD_DIMENSION &&
            boardState[row - i][col] == boardState[row - i + 1][col] &&
            boardState[row - i][col] == boardState[row - i + 2][col] &&
            boardState[row - i][col] == boardState[row - i + 3][col] &&
            boardState[row - i][col] == boardState[row - i + 4][col])
            return true;
    }

    // 左斜方向
    for (int i = 0; i < 5; i++)
    {
        if (row + i < BOARD_DIMENSION &&
            row + i - 4 > 0 &&
            col - i > 0 &&
            col - i + 4 < BOARD_DIMENSION &&
            boardState[row + i][col - i] == boardState[row + i - 1][col - i + 1] &&
            boardState[row + i][col - i] == boardState[row + i - 2][col - i + 2] &&
            boardState[row + i][col - i] == boardState[row + i - 3][col - i + 3] &&
            boardState[row + i][col - i] == boardState[row + i - 4][col - i + 4])
            return true;
    }

    // 右斜方向
    for (int i = 0; i < 5; i++)
    {
        if (row - i > 0 &&
            row - i + 4 < BOARD_DIMENSION &&
            col - i > 0 &&
            col - i + 4 < BOARD_DIMENSION &&
            boardState[row - i][col - i] == boardState[row - i + 1][col - i + 1] &&
            boardState[row - i][col - i] == boardState[row - i + 2][col - i + 2] &&
            boardState[row - i][col - i] == boardState[row - i + 3][col - i + 3] &&
            boardState[row - i][col - i] == boardState[row - i + 4][col - i + 4])
            return true;
    }

    return false;
}

bool GomokuGameEngine::checkDraw()
{
    for (int i = 1; i < BOARD_DIMENSION; i++)
        for (int j = 1; j < BOARD_DIMENSION; j++)
        {
            if (!(boardState[i][j] == 1 || boardState[i][j] == -1))
                return false;
        }
    return true;
}
